/**
 * @brief 菜单文件(new)
 * @note MainMenuLength 定义了选项的总个数
 * MaxDisplayLine 定义了一页能显示的个数
 * 此文件依赖于显示和按键
 * 菜单中要执行的函数放在menuEXE.c中
 */
#include "ABS_key.h"
#include "C_code_Log.h"
#include "display.h"
#include "globalTime.h"
#include "menu.h"
#include "menuEXE.h"

#define MainMenuLength 22  // 最大的菜单项数
#define MaxDisplayLine 10  // 每页最大显示的菜单项数
#define MaxPages \
  ((MainMenuLength + MaxDisplayLine - 1) / MaxDisplayLine)  // 最大页数
#define LastPageLine                                        \
  ((MainMenuLength + MaxDisplayLine - 1) % MaxDisplayLine + \
   1)  // 最后一页的菜单项数

/// @brief 示例函数
/// @return
My_StatusTypeDef noDo(int key_Num) {
  static int num = 4;
  displayNum(num, Display_firstCol, Display_firstRow);
  if (key_Num == Key_ESC) {
    return MY_READY;
  } else if (key_Num == Key_OK) {
    return MY_STANDBY;
  } else if (key_Num == Key_Down) {
    num--;
  } else if (key_Num == Key_UP) {
    num++;
  }

  return MY_BUSY;
}

/// @brief 菜单列表
menuList_t mainMenuList[MainMenuLength] = {
    {"Fun_Debug", Fun_debug},
    {"Fun_GAME",Fun_Run},
    {"Fun_GAME_2",Fun_GAME},
    {"AutoWayDebug",Fun_AutoWayDebug},
    {"AutoWayAdd",AutoWayAdd},
    {"AutoWayRemove",AutoWayRemove},
    {"speed", displaySpeed},
    {"testPWM", testEncodingAndPWM},
    {"PWMDirect", PWMTest},
    {"testOneMetre", testOneMetre},
    {"BuildTime", buildTime},
    {"game", gameDebug},
    {"new", noDo},
    {"servo",servo},
    {"fineLine",findLine},
    {"Gyro_Test",Gyro_Test},
    {"camera_Test",camera_Test},
    {"colorTest",ColorTest},
    {"EEPROM_Test",EEPROMTest},
    {"switchTest",switchTest},
    {"ChineseTest",ChineseTest},
    {"CAN_Test",CAN_Test},
};
/// @brief 显示光标 @note 仅供menuDisplay() 调用
/// @param cursor 光标的行数
///@author Sevenfite
static void displayCursor(int cursor) {
  static int temp = 1;
  if (cursor == temp) {
    displayStr("<", Display_lastCol, (cursor - 1) * Display_spaced, RED);
  } else {
    displayStr(" ", Display_lastCol, (temp - 1) * Display_spaced, RED);
    displayStr("<", Display_lastCol, (cursor - 1) * Display_spaced, RED);
    temp = cursor;
  }
}
/**
 *@brief 菜单显示
 *@note
 *按向上向下可以控制光标，光标的显示位置的x坐标是通过宏定义(Display_lastCol)来决定的
 *      按OK键进入执行函数
 *      @arg MY_BUSY再次执行此函数，
 *      @arg MY_OK为退出
 * @author Sevenfite
 * @note
 *进入菜单函数的实现方式：在这里执行按键的扫描，将键值传给目标函数，函数自行处理,
 * @note 函数中不做按键扫描，但是必须做ESC值的判断处理，返回MY_OK/MY_READY
 * @note             按OK之后，循环执行函数，
 * @note 如果按了ESC，则将ESC传给函数，函数必须返回MY_OK，才能退出循环
 * @note             如果按了OK，则将OK传给函数，由函数自行处理
 * @note             如果按了上下键，则将上下键传给函数，由函数自行处理
 * @note 更改：2024/1/8 在执行函数时，不做卡死处理，方便在其他地方做轮询
 */
void menuDisplay(void) {
  static int8_t keyNum = 0;     // 0表示没有按键按下
  static int8_t cursor = 1;     // 光标的行数(>=1)
  static int8_t pages = 1;      // 页数(>=1)
  static int8_t pagesTurn = 1;  // 页数是否翻转,1表示翻页
  static int8_t runFlag = 0;  // 0表示没有进入函数，1表示进入函数，正在执行函数
  My_StatusTypeDef runState = MY_STANDBY;
  keyNum = key_scan_noDelay(1, getGlobalTime());
  if (runFlag == 1) {
    // 实现方式：在这里执行按键的扫描，将键值传给函数，函数自行处理，
    // 函数中不做按键扫描，但是必须做ESC值的判断处理，返回MY_OK/MY_READY
    // 按OK之后，循环执行函数，
    // 如果按了ESC，则将ESC传给函数，函数必须返回MY_OK，才能退出循环
    // 如果按了OK，则将OK传给函数，由函数自行处理
    // 如果按了上下键，则将上下键传给函数，由函数自行处理
    if (keyNum == 0) {
      mainMenuList[(cursor - 1 + (pages - 1) * MaxDisplayLine)].exe(0);
    } else if (keyNum == Key_ESC) {  // 按ESC退出
      runState = mainMenuList[(cursor - 1 + (pages - 1) * MaxDisplayLine)].exe(
          Key_ESC);
      if (runState == MY_OK) {  // 如果函数返回MY_OK，则清屏后退出
        displayClean();
        pagesTurn = 1;
        runState = MY_STANDBY;
        runFlag = 0;
      }
    } else if (keyNum == Key_OK) {
      mainMenuList[(cursor - 1 + (pages - 1) * MaxDisplayLine)].exe(Key_OK);
    } else if (keyNum == Key_Down) {
      mainMenuList[(cursor - 1 + (pages - 1) * MaxDisplayLine)].exe(Key_Down);
    } else if (keyNum == Key_UP) {
      mainMenuList[(cursor - 1 + (pages - 1) * MaxDisplayLine)].exe(Key_UP);
    }
  } else if (runFlag == 0) {
    switch (keyNum) {
      case Key_Down:
        cursor++;
        pagesTurn = 0;
        if (cursor > MaxDisplayLine) {
          pages++;
          pages = (pages - 1) % MaxPages + 1;
          cursor = 1;
          displayClean();
          pagesTurn = 1;
        }
        if (pages == MaxPages) {
          if (cursor > LastPageLine) {
            pages = 1;
            cursor = 1;
            displayClean();
            pagesTurn = 1;
          }
        }
        break;
        
      case Key_UP:
        cursor--;
        pagesTurn = 0;
        if (cursor < 1) {
          pages--;
          if (pages < 1) {
            pages = MaxPages;
            cursor = LastPageLine;
          } else {
            cursor = MaxDisplayLine;
          }
          displayClean();
          pagesTurn = 1;
        }
        break;

      case Key_OK:
        displayClean();
        runFlag = 1;
        return;
        break;

      default:
        break;
    }
    // 显示标题
    if (pagesTurn == 1) {
      if (pages == MaxPages) {
        for (int i = 0; i < LastPageLine; i++) {
          displayStr(mainMenuList[i + (pages - 1) * MaxDisplayLine].str,
                     Display_firstCol, i * Display_spaced, RED);
        }
      } else {
        for (int i = 0; i < MaxDisplayLine; i++) {
          displayStr(mainMenuList[i + (pages - 1) * MaxDisplayLine].str,
                     Display_firstCol, i * Display_spaced, RED);
        }
      }
      pagesTurn = 0;
    }
    displayCursor(cursor);  // 显示光标
  }
}
